<?php  
if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
 * 
 * 后台模块管理模型类
 * @author 66diqiu-li
 *
 */
class Admin_Modules_model extends CI_Model {
	
    //应用模块目录
    public $appPath = '';
    //错误信息
    public $error = NULL;
	//模块配置
    private $config = array();
    //当前模块名称
    private $moduleName = NULL;
    //当前类数据前缀
    private $dbprefix = '';
	
    /**
     * 
     * 构造函数
     */
    public function __construct(){
    	parent::__construct();
    	$this->appPath = getcwd() . '/'.MODPATH;
    }
    
    /**
     * 
     * 获取模块基本配置信息
     * @param type $moduleName 模块名(目录名)
     */
	function config($moduleName = ''){
        if (!empty($this->config) && empty($moduleName)) {
            return $this->config;
        }
        if (empty($moduleName)) {
            if ($this->moduleName) {
                $moduleName = $this->moduleName;
            } else {
                $this->error = '模块名称不能为空！';
                return false;
            }
        }
        $config = array(
            //模块目录
            'module' => $moduleName,
            //模块名称
            'modulename' => $moduleName,
            //图标地址，远程地址
            'icon' => '',
            //模块介绍地址
            'address' => '',
            //模块简介
            'introduce' => '',
            //模块作者
            'author' => '',
            //作者地址
            'authorsite' => '',
            //作者邮箱
            'authoremail' => '',
            //版本号，请不要带除数字外的其他字符
            'version' => '',
            //适配最低66diqiu版本，
            'adaptation' => '',
            //签名
            'sign' => '',
            //依赖模块
            'depend' => array(),
        );
        //加载安装配置文件
        if (file_exists($this->appPath . $moduleName . '/config.inc.php')) {
            //加载
            try {
                $moduleConfig = include $this->appPath . $moduleName . '/config.inc.php';
                $config = array_merge($config, $moduleConfig);
            } catch (Exception $exc) {
                
            }
        }
        if(empty($config['icon'])){
        	$config['icon'] = URLPRE.'static/public/images/module.png';
        }
        //检查是否安装，如果安装了，加载模块安装后的相关配置信息
        if ($this->isInstall($moduleName)) {
            //已安装模块
		    $data = $this->get_list();
		    $moduleList = array();
		    foreach($data as $v){
		        $moduleList[$v['module']] = $v;
		    }
            $config = array_merge($moduleList[$moduleName], $config);
        }
        $this->config = $config;
        return $config;
	}
	
	/**
     * 执行模块安装
     * @param type $moduleName 模块名(目录名)
     * @return boolean
     */
    public function install($moduleName = '',$dbprefix='') {
        if (empty($moduleName)) {
            if ($this->moduleName) {
                $moduleName = $this->moduleName;
            } else {
                $this->error = '请选择需要安装的模块！';
                return false;
            }
        }
        //设置脚本最大执行时间
        set_time_limit(0);
        
        if($dbprefix!=''){
            $this->dbprefix = $dbprefix;
        }
        else {
            $this->dbprefix = $this->db->dbprefix;
        }
        $table = $this->dbprefix.'admin_modules';

        //加载模块基本配置
        $config = $this->config($moduleName);
        $version = read_file('version.txt');
        //版本检查
        if ($config['adaptation']) {
            if (version_compare($version, $config['adaptation'], '>=') == false) {
                $this->error = '该模块要求系统最低版本为：' . $config['adaptation'] . '！';
                return false;
            }
        }

        //依赖模块检测
        //取得该模块数据库中记录的安装信息
        if (!empty($config['depend']) && is_array($config['depend'])){
            foreach ($config['depend'] as $mod) {
                $query = $this->db->query("SELECT module as num FROM ".$table." WHERE module='".$mod."'");
                $row = $query->row();
                if (empty($row->num)) {
                    $this->error = "安装该模块，需要安装依赖模块 {$mod} !";
                    return false;
                }
            }
        }
        //检查模块是否已经安装
        if ($this->isInstall($moduleName)) {
            $this->error = '该模块已经安装，无法重复安装！';
            return false;
        }
        
        //创建安装模块数据
        $create_data['module'] = $config['module'];
        $create_data['modulename'] = $config['modulename'];
        $create_data['version'] = $config['version'];
        $create_data['install_time'] = date('Y-m-d H:i:s',now());
        if (!$this->db->insert($table, $create_data)) {
            $this->error = '安装初始化失败！';
            return false;
        }
        
        //执行数据库脚本安装
        $this->runSQL($moduleName);
        $this->runSQL($moduleName, 'update');

        //执行菜单项安装
        if ($this->installMenu($moduleName) !== true) {
        	$this->error = "该模块菜单项没有加载成功!";
        	$this->installRollback($moduleName);
            return false;
        }
        //复制静态文件到相应目录
        $this->copy_static_files($moduleName);
        return true;
    }
    
    /**
     * 模块卸载
     * @param type $moduleName 模块名(目录名)
     * @return boolean
     */
    public function uninstall($moduleName = '') {
        if (empty($moduleName)) {
            if ($this->moduleName) {
                $moduleName = $this->moduleName;
            } else {
                $this->error = '请选择需要卸载的模块！';
                return false;
            }
        }
        //设置脚本最大执行时间
        set_time_limit(0);
        
        $table = $this->db->dbprefix("admin_modules"); 
        $query = $this->db->query("SELECT iscore FROM ".$table." WHERE module='".$moduleName."'");
        $row = $query->row();
        if (empty($row)) {
            $this->error = '该模块未安装，无需卸载！';
            return false;
        }
        if ($row->iscore) {
            $this->error = '内置模块，不能卸载！';
            return false;
        }
        //删除
        if(!$this->db->delete($table, array('module' => $moduleName))){
            $this->error = '卸载失败！';
            return false;
        }
        
        //删除菜单项
        $this->load->model('admin.Menu_model');
        $this->Menu_model->uninstallMenu($moduleName);
        
        //执行数据库脚本安装
        $this->runSQL($moduleName, 'uninstall');
        
        //删除模块对应的静态文件
        $this->remove_static_files($moduleName);
        return true;
    }
	
    /**
     * 是否已经安装
     * @param type $moduleName 模块名(目录名)
     * @return boolean
     */
    public function isInstall($moduleName = '') {
        if (empty($moduleName)) {
            if ($this->moduleName) {
                $moduleName = $this->moduleName;
            } else {
                $this->error = '模块名称不能为空！';
                return false;
            }
        }
        $table = $this->dbprefix.'admin_modules';
        $this->db->select('module');
        $query = $this->db->get_where($table,array('module'=>$moduleName),1);
        $res = $query->result();
        return !empty($res) ? true : false;
    }
    
    /**
     * 执行安装数据库脚本
     * @param type $moduleName 模块名(目录名)
     * @return boolean
     */
    public function runSQL($moduleName = '', $Dir = 'install', $sql = '') {
        if (empty($moduleName)) {
            if ($this->moduleName) {
                $moduleName = $this->moduleName;
            } else {
                $this->error = '模块名称不能为空！';
                return false;
            }
        }
        $path = $this->appPath . "{$moduleName}/{$Dir}/{$moduleName}.sql";
        if (!file_exists($path)) {
            return true;
        }
        $sql = empty($sql) ? file_get_contents($path) : $sql;
        $sql = $this->resolveSQL($sql, $this->db->dbprefix);
        if (!empty($sql) && is_array($sql)) {
            foreach ($sql as $sql_split) {
                $this->db->query($sql_split);
            }
        }
        return true;
    }
    
    /**
     * 分析处理sql语句，执行替换前缀都功能。
     * @param string $sql 原始的sql
     * @param string $tablepre 表前缀
     */
    private function resolveSQL($sql, $tablepre) {
        if ($tablepre != "66diqiu_")
            $sql = str_replace("66diqiu_", $tablepre, $sql);
        $sql = preg_replace("/TYPE=(InnoDB|MyISAM|MEMORY)( DEFAULT CHARSET=[^; ]+)?/", "ENGINE=\\1 DEFAULT CHARSET=utf8", $sql);
        
        $sql = str_replace("\r", "\n", $sql);
        $ret = array();
        $num = 0;
        $queriesarray = explode(";\n", trim($sql));
        unset($sql);
        foreach ($queriesarray as $query) {
            $ret[$num] = '';
            $queries = explode("\n", trim($query));
            $queries = array_filter($queries);
            foreach ($queries as $query) {
                $str1 = substr($query, 0, 1);
                if ($str1 != '#' && $str1 != '-')
                    $ret[$num] .= $query;
            }
            $num++;
        }
        return $ret;
    }

    /**
     * 安装菜单项
     * @param type $moduleName 模块名称
     * @param type $file 文件
     * @return boolean
     */
    private function installMenu($moduleName = '', $file = 'menu') 
    {
        if (empty($moduleName)) {
            if ($this->moduleName) {
                $moduleName = $this->moduleName;
            } else {
                $this->error = '模块名称不能为空！';
                return false;
            }
        }
        $path = $this->appPath . "{$moduleName}/install/{$file}.php";
        //检查是否有安装脚本
        if (!file_exists($path)) {
            return true;
        }
        $menu = include $path;
        if (empty($menu)) {
            return true;
        }
        
        //安装菜单项
        $this->load->model('admin.Menu_model');
        $status = $this->Menu_model->installModuleMenu($menu, $this->config($moduleName),$this->dbprefix);
        if ($status === true) {
            return true;
        } else {
            $this->error = '安装菜单项出现错误！';
            return false;
        }
    }
    
    /**
     * 安装回滚
     * @param type $moduleName 模块名(目录名)
     */
    private function installRollback($moduleName = '') {
        if (empty($moduleName)) {
            if ($this->moduleName) {
                $moduleName = $this->moduleName;
            } else {
                $this->error = '模块名称不能为空！';
                return false;
            }
        }
        //删除安装状态
        $table = $this->db->dbprefix("admin_modules"); 
        $this->db->delete($table, array('module' => $moduleName));
    }
    
    /**
     * 
     * 获取已经安装好的模块
     */
    public function get_list($dbprefix=''){
        $table = $this->dbprefix.'admin_modules';
    	$this->db->select('module,modulename,iscore,version,install_time');
        $query = $this->db->get($table);
        $data = array();
	    foreach ($query->result_array() as $row)
		{
            $data[] = $row;
		}
		return $data;
    }
    
    /**
     * 
     * 复制静态文件到相应的静态文件目录
     * @param string $moduleName 模块名称
     */
    public function copy_static_files($moduleName = ''){
    	$path = $this->appPath . "{$moduleName}/static";
    	if(file_exists($path)){
    		$dst = getcwd().'/static/'.$moduleName;
    	    recurse_copy($path, $dst);
    	}
    }
    
    /**
     * 
     * 卸载模块时删除相应的安装静态文件
     * @param string $moduleName 模块名称
     */
    public function remove_static_files($moduleName = ''){
        $path = getcwd().'/static/'.$moduleName;
    	if(file_exists($path)){
    		return del_dir($path);
    	}
    }
}